/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2022-04-26 15:25:24
 * @LastEditors: ding
 * @LastEditTime: 2022-10-11 18:32:58
 * @Description: 钉钉用户员工操作
 */

import DingTalkBasePublicService from "./BasePublicService";
import { Dingtalk } from "../dingtalk";
import * as crypto from "crypto";
import * as querystring from "querystring";

export default class UserService extends DingTalkBasePublicService {
	/** 根据部门id查询用户详情列表 */
	async getUserDetailListByPartId(dept_id: number) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/list`);
		const method = "POST";

		const list: Dingtalk.ov.IResponseGetUserDetailByPart["result"]["list"] = [];
		const doget = async (cursor) => {
			const data = {
				dept_id,
				cursor,
				size: 100,
				order_field: "entry_desc",
				contain_access_limit: true,
				language: "zh_CN",
			};

			const res = await this.curl<Dingtalk.ov.IResponseGetUserDetailByPart>(url, {
				method,
				data,
				contentType: "json",
				dataType: "json",
			});
			this.ovcheckError(url, res);
			list.push(...res.data.result.list);
			if (res.data.result.has_more) {
				await doget(res.data.result.next_cursor);
			}
		};
		await doget(0);

		return list;
	}

	/** 创建新用户 */
	async createUser(userInfo: Dingtalk.ov.IRequestCreateUser) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/create`);

		const res = await this.curl<Dingtalk.ov.IResponseCreateUser>(url, {
			contentType: "json",
			dataType: "json",
			method: "POST",
			data: userInfo,
		});
		this.ovcheckError(url, res);
		return res.data;
	}

	/** 更新用户 */
	async updateUser(userInfo: Dingtalk.ov.IRequestUpdateUser) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/update`);

		const res = await this.curl<Dingtalk.ov.IResponseCommon>(url, {
			contentType: "json",
			dataType: "json",
			method: "POST",
			data: userInfo,
		});
		this.ovcheckError(url, res);
		return true;
	}

	/**
	 *查询用户数量
	 *
	 * @param {string} accesstoken
	 * @param {boolean} only_active 是否只查询已激活钉钉的数量
	 * @return {*}
	 * @memberof PlatformDingtalkBaseUserService
	 */
	async getUserCount(only_active: boolean = true) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/user/count`);
		const res = await this.curl<Dingtalk.ov.IResponseGetUserCount>(url, {
			dataType: "json",
			method: "POST",
			contentType: "json",
			data: {
				only_active,
			},
		});
		this.ovcheckError(url, res);
		return res.data;
	}

	/**
	 * 删除用户
	 *
	 * @param {string} accessToken
	 * @param {string} userid
	 * @return {*}
	 * @memberof PlatformDingtalkBaseUserService
	 */
	async deleteUser(userid: string) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/delete`);
		const method = "POST";

		const data = {
			userid,
		};

		type TResponse = Dingtalk.ov.IResponseCommon & {
			request_id: string;
		};
		const res = await this.curl<TResponse>(url, {
			contentType: "json",
			method: method,
			dataType: "json",
			data,
		});
		this.ovcheckError(url, res);
		return true;
	}

	/**
	 *查询一个员工的详细信息
	 *
	 * @param {string} access_token
	 * @param {string} userid 用户id
	 * @param {string} [language="zh_CN"] 语言，默认中文
	 * @return {*}
	 * @memberof PlatformDingtalkBaseUserService
	 */
	async getUserDetail(userid: string, language: string = "zh_CN") {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/get`);
		const method = "POST";
		const data = {
			userid,
			language,
		};
		const res = await this.curl<Dingtalk.ov.IResponseGetUser>(url, {
			contentType: "json",
			dataType: "json",
			method,
			data,
		});
		this.ovcheckError(url, res);
		return res.data;
	}

	/**
	 *根据用户手机号查询用户userid
	 *
	 * @param {string} access_token
	 * @param {string} mobile
	 * @return {*}
	 * @memberof PlatformDingtalkBaseUserService
	 */
	async getUseridByMobile(mobile: string) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/v2/user/getbymobile`);

		const method = "POST";
		const data = {
			mobile: mobile,
		};
		const res = await this.curl<Dingtalk.ov.IResponseGetUseridByMobile>(url, {
			contentType: "json",
			dataType: "json",
			method,
			data,
		});
		this.ovcheckError(url, res);
		return res.data;
	}

	/** 根据用户unionId查询userid */
	async getUserIdByUnionId(unionid: string) {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/user/getbyunionid`);

		const method = "POST";
		const data = {
			unionid: unionid,
		};
		const res = await this.curl<Dingtalk.ov.IResponseGetUseridByUnionId>(url, {
			contentType: "json",
			dataType: "json",
			method,
			data,
		});
		this.ovcheckError(url, res);
		return res.data.result;
	}

	/**
	 * 获取管理员列表
	 *
	 * @param {string} access_token
	 * @return {*}
	 * @memberof PlatformDingtalkBaseUserService
	 */
	async getAdminList() {
		const url = await this.getURL(`https://oapi.dingtalk.com/topapi/user/listadmin`);
		const method = "POST";

		const res = await this.curl<Dingtalk.ov.IResponseGetAdminListUser>(url, {
			contentType: "json",
			dataType: "json",
			method,
		});

		this.ovcheckError(url, res);
		return res.data;
	}

	/**
	 * - 旧版接口
	 * - 通过sns临时授权码获取用户信息，用于第三方网站在钉钉内自动登录功能等
	 * - https://open.dingtalk.com/document/isvapp/obtain-the-user-information-based-on-the-sns-temporary-authorization
	 */
	async getUserInfoByCode(tmp_auth_code: string) {
		const config = this.config;
		const appKey = config.clientId;
		const appSecret = config.clientSecret;
		const timestamps = new Date().getTime();
		// 计算签名的算法
		const signer = () => {
			const hmac = crypto.createHmac("sha256", appSecret);
			// @ts-ignore 注意此处，报错ts，可能新版本node不接收buffer。
			hmac.update(Buffer.from(timestamps.toString()));
			const base64 = hmac.digest("base64");
			// return this.app.tools.querystring.encode(base64);
			return base64;
			// return encodeURIComponent(base64);
		};
		const signature = signer();
		const queryStr = querystring.encode({ signature, accessKey: appKey, timestamp: timestamps });
		const method = "POST";
		const url = `https://oapi.dingtalk.com/sns/getuserinfo_bycode?${queryStr}`;
		const res = await this.curl<Dingtalk.ov.IResponseGetUserInfoByTempCode>(url, {
			contentType: "json",
			dataType: "json",
			method,
			data: {
				tmp_auth_code,
			},
		});
		this.app.coreLogger.debug(`钉钉临时sns授权码获取用户信息 \r\n%j`, res.data);
		this.ovcheckError(url, res);
		return res.data;
	}
}
